function div(a, b) {
	return (a - (a % b)) / b;
}

BigDecimal.prototype.div = div;

function arraycopy(src, srcindex, dest, destindex, length) {
	var i;
	if (destindex > srcindex) {
		// in case src and dest are equals, but also doesn't hurt
		// if they are different
		for (i = length - 1; i >= 0; --i) {
			dest[i + destindex] = src[i + srcindex];
		}
	} else {
		for (i = 0; i < length; ++i) {
			dest[i + destindex] = src[i + srcindex];
		}
	}
}

BigDecimal.prototype.arraycopy = arraycopy;

function createArrayWithZeros(length) {
	var retVal = new Array(length);
	var i;
	for (i = 0; i < length; ++i) {
		retVal[i] = 0;
	}
	return retVal;
}

BigDecimal.prototype.createArrayWithZeros = createArrayWithZeros;

BigDecimal.prototype.abs = abs;
BigDecimal.prototype.add = add;
BigDecimal.prototype.compareTo = compareTo;
BigDecimal.prototype.divide = divide;
BigDecimal.prototype.divideInteger = divideInteger;
BigDecimal.prototype.max = max;
BigDecimal.prototype.min = min;
BigDecimal.prototype.multiply = multiply;
BigDecimal.prototype.negate = negate;
BigDecimal.prototype.plus = plus;
BigDecimal.prototype.pow = pow;
BigDecimal.prototype.remainder = remainder;
BigDecimal.prototype.subtract = subtract;
BigDecimal.prototype.equals = equals;
BigDecimal.prototype.format = format;
BigDecimal.prototype.intValueExact = intValueExact;
BigDecimal.prototype.movePointLeft = movePointLeft;
BigDecimal.prototype.movePointRight = movePointRight;
BigDecimal.prototype.scale = scale;
BigDecimal.prototype.setScale = setScale;
BigDecimal.prototype.signum = signum;
BigDecimal.prototype.toString = toString;
BigDecimal.prototype.layout = layout;
BigDecimal.prototype.intcheck = intcheck;
BigDecimal.prototype.dodivide = dodivide;
BigDecimal.prototype.bad = bad;
BigDecimal.prototype.badarg = badarg;
BigDecimal.prototype.extend = extend;
BigDecimal.prototype.byteaddsub = byteaddsub;
BigDecimal.prototype.diginit = diginit;
BigDecimal.prototype.clone = clone;
BigDecimal.prototype.checkdigits = checkdigits;
BigDecimal.prototype.round = round;
BigDecimal.prototype.allzero = allzero;
BigDecimal.prototype.finish = finish;

BigDecimal.prototype.ROUND_CEILING = MathContext.prototype.ROUND_CEILING;

BigDecimal.prototype.ROUND_DOWN = MathContext.prototype.ROUND_DOWN;

BigDecimal.prototype.ROUND_FLOOR = MathContext.prototype.ROUND_FLOOR;

BigDecimal.prototype.ROUND_HALF_DOWN = MathContext.prototype.ROUND_HALF_DOWN;

BigDecimal.prototype.ROUND_HALF_EVEN = MathContext.prototype.ROUND_HALF_EVEN;

BigDecimal.prototype.ROUND_HALF_UP = MathContext.prototype.ROUND_HALF_UP;

BigDecimal.prototype.ROUND_UNNECESSARY = MathContext.prototype.ROUND_UNNECESSARY;

BigDecimal.prototype.ROUND_UP = MathContext.prototype.ROUND_UP;

BigDecimal.prototype.ispos = 1;

BigDecimal.prototype.iszero = 0;

BigDecimal.prototype.isneg = -1;

BigDecimal.prototype.MinExp = -999999999; // minimum exponent allowed

BigDecimal.prototype.MaxExp = 999999999; // maximum exponent allowed

BigDecimal.prototype.MinArg = -999999999; // minimum argument integer

BigDecimal.prototype.MaxArg = 999999999; // maximum argument integer

BigDecimal.prototype.plainMC = new MathContext(0, MathContext.prototype.PLAIN);

BigDecimal.prototype.bytecar = new Array((90 + 99) + 1);

BigDecimal.prototype.bytedig = diginit();

BigDecimal.prototype.ZERO = new BigDecimal("0");

BigDecimal.prototype.ONE = new BigDecimal("1");

BigDecimal.prototype.TEN = new BigDecimal("10");

function BigDecimal() {
	// -- members
	this.ind = 0;
	this.form = MathContext.prototype.PLAIN;
	this.mant = null;
	this.exp = 0;

	// -- overloaded ctor
	if (BigDecimal.arguments.length == 0)
		return;
	var inchars;
	var offset;
	var length;
	if (BigDecimal.arguments.length == 1) {
		inchars = BigDecimal.arguments[0];
		offset = 0;
		length = inchars.length;
	} else {
		inchars = BigDecimal.arguments[0];
		offset = BigDecimal.arguments[1];
		length = BigDecimal.arguments[2];
	}
	if (typeof inchars == "string") {
		inchars = inchars.split("");
	}

	// --boolean exotic;
	var exotic;
	// --boolean hadexp;
	var hadexp;
	// --int d;
	var d;
	// --int dotoff;
	var dotoff;
	// --int last;
	var last;
	// --int i=0;
	var i = 0;
	// --char si=0;
	var si = 0;
	// --boolean eneg=false;
	var eneg = false;
	// --int k=0;
	var k = 0;
	// --int elen=0;
	var elen = 0;
	// --int j=0;
	var j = 0;
	// --char sj=0;
	var sj = 0;
	// --int dvalue=0;
	var dvalue = 0;
	// --int mag=0;
	var mag = 0;
	// This is the primary constructor; all incoming strings end up
	// here; it uses explicit (inline) parsing for speed and to avoid
	// generating intermediate (temporary) objects of any kind.
	// 1998.06.25: exponent form built only if E/e in string
	// 1998.06.25: trailing zeros not removed for zero
	// 1999.03.06: no embedded blanks; allow offset and length
	if (length <= 0)
		this.bad("BigDecimal(): ", inchars); // bad conversion (empty string)
	// [bad offset will raise array bounds exception]

	/* Handle and step past sign */
	this.ind = this.ispos; // assume positive
	if (inchars[0] == ('-')) {
		length--;
		if (length == 0)
			this.bad("BigDecimal(): ", inchars); // nothing after sign
		this.ind = this.isneg;
		offset++;
	} else if (inchars[0] == ('+')) {
		length--;
		if (length == 0)
			this.bad("BigDecimal(): ", inchars); // nothing after sign
		offset++;
	}

	/* We're at the start of the number */
	exotic = false; // have extra digits
	hadexp = false; // had explicit exponent
	d = 0; // count of digits found
	dotoff = -1; // offset where dot was found
	last = -1; // last character of mantissa
	{
		var $1 = length;
		i = offset;
		i: for (; $1 > 0; $1--, i++) {
			si = inchars[i];
			if (si >= '0') // test for Arabic digit
				if (si <= '9') {
					last = i;
					d++; // still in mantissa
					continue i;
				}
			if (si == '.') { // record and ignore
				if (dotoff >= 0)
					this.bad("BigDecimal(): ", inchars); // two dots
				dotoff = i - offset; // offset into mantissa
				continue i;
			}
			if (si != 'e')
				if (si != 'E') { // expect an extra digit
					if (si < '0' || si > '9')
						this.bad("BigDecimal(): ", inchars); // not a number
					// defer the base 10 check until later to avoid extra method
					// call
					exotic = true; // will need conversion later
					last = i;
					d++; // still in mantissa
					continue i;
				}
			/* Found 'e' or 'E' -- now process explicit exponent */
			// 1998.07.11: sign no longer required
			if ((i - offset) > (length - 2))
				this.bad("BigDecimal(): ", inchars); // no room for even one
			// digit
			eneg = false;
			if ((inchars[i + 1]) == ('-')) {
				eneg = true;
				k = i + 2;
			} else if ((inchars[i + 1]) == ('+'))
				k = i + 2;
			else
				k = i + 1;
			// k is offset of first expected digit
			elen = length - ((k - offset)); // possible number of digits
			if ((elen == 0) || (elen > 9))
				this.bad("BigDecimal(): ", inchars); // 0 or more than 9
			// digits
			{
				var $2 = elen;
				j = k;
				j: for (; $2 > 0; $2--, j++) {
					sj = inchars[j];
					if (sj < '0')
						this.bad("BigDecimal(): ", inchars); // always bad
					if (sj > '9') { // maybe an exotic digit
						/*
						 * if (si<'0' || si>'9') this.bad(inchars); // not a
						 * number dvalue=java.lang.Character.digit(sj,10); //
						 * check base if (dvalue<0) bad(inchars); // not base
						 * 10
						 */
						this.bad("BigDecimal(): ", inchars);
					} else
						dvalue = sj - '0';
					this.exp = (this.exp * 10) + dvalue;
				}
			}/* j */
			if (eneg)
				this.exp = -this.exp; // was negative
			hadexp = true; // remember we had one
			break i; // we are done
		}
	}/* i */

	/* Here when all inspected */
	if (d == 0)
		this.bad("BigDecimal(): ", inchars); // no mantissa digits
	if (dotoff >= 0)
		this.exp = (this.exp + dotoff) - d; // adjust exponent if had dot

	/* strip leading zeros/dot (leave final if all 0's) */
	{
		var $3 = last - 1;
		i = offset;
		i: for (; i <= $3; i++) {
			si = inchars[i];
			if (si == '0') {
				offset++;
				dotoff--;
				d--;
			} else if (si == '.') {
				offset++; // step past dot
				dotoff--;
			} else if (si <= '9')
				break i;/* non-0 */
			else {/* exotic */
				// if ((java.lang.Character.digit(si,10))!=0)
				break i; // non-0 or bad
				// is 0 .. strip like '0'
				// offset++;
				// dotoff--;
				// d--;
			}
		}
	}/* i */

	/* Create the mantissa array */
	this.mant = new Array(d); // we know the length
	j = offset; // input offset
	if (exotic) {
		exotica: do { // slow: check for exotica
			{
				var $4 = d;
				i = 0;
				i: for (; $4 > 0; $4--, i++) {
					if (i == dotoff)
						j++; // at dot
					sj = inchars[j];
					if (sj <= '9')
						this.mant[i] = sj - '0';/* easy */
					else {
						// dvalue=java.lang.Character.digit(sj,10);
						// if (dvalue<0)
						this.bad("BigDecimal(): ", inchars); // not a number
						// after all
						// mant[i]=(byte)dvalue;
					}
					j++;
				}
			}/* i */
		} while (false);
	}/* exotica */
	else {
		simple: do {
			{
				var $5 = d;
				i = 0;
				i: for (; $5 > 0; $5--, i++) {
					if (i == dotoff)
						j++;
					this.mant[i] = inchars[j] - '0';
					j++;
				}
			}/* i */
		} while (false);
	}/* simple */

	/* Looks good. Set the sign indicator and form, as needed. */
	// Trailing zeros are preserved
	// The rule here for form is:
	// If no E-notation, then request plain notation
	// Otherwise act as though add(0,DEFAULT) and request scientific notation
	// [form is already PLAIN]
	if (this.mant[0] == 0) {
		this.ind = this.iszero; // force to show zero
		// negative exponent is significant (e.g., -3 for 0.000) if plain
		if (this.exp > 0)
			this.exp = 0; // positive exponent can be ignored
		if (hadexp) { // zero becomes single digit from add
			this.mant = this.ZERO.mant;
			this.exp = 0;
		}
	} else { // non-zero
		// [ind was set earlier]
		// now determine form
		if (hadexp) {
			this.form = MathContext.prototype.SCIENTIFIC;
			// 1999.06.29 check for overflow
			mag = (this.exp + this.mant.length) - 1; // true exponent in
			// scientific notation
			if ((mag < this.MinExp) || (mag > this.MaxExp))
				this.bad("BigDecimal(): ", inchars);
		}
	}
	// say 'BD(c[]): mant[0] mantlen exp ind form:' mant[0] mant.length exp ind
	// form
	return;
}

function abs() {
	var set;
	if (abs.arguments.length == 1) {
		set = abs.arguments[0];
	} else if (abs.arguments.length == 0) {
		set = this.plainMC;
	} else {
		throw "abs(): " + abs.arguments.length
				+ " arguments given; expected 0 or 1"
	}
	if (this.ind == this.isneg)
		return this.negate(set);
	return this.plus(set);
}

function add() {
	var set;
	if (add.arguments.length == 2) {
		set = add.arguments[1];
	} else if (add.arguments.length == 1) {
		set = this.plainMC;
	} else {
		throw "add(): " + add.arguments.length
				+ " arguments given; expected 1 or 2"
	}
	var rhs = add.arguments[0];
	// --com.ibm.icu.math.BigDecimal lhs;
	var lhs;
	// --int reqdig;
	var reqdig;
	// --com.ibm.icu.math.BigDecimal res;
	var res;
	// --byte usel[];
	var usel;
	// --int usellen;
	var usellen;
	// --byte user[];
	var user;
	// --int userlen;
	var userlen;
	// --int newlen=0;
	var newlen = 0;
	// --int tlen=0;
	var tlen = 0;
	// --int mult=0;
	var mult = 0;
	// --byte t[]=null;
	var t = null;
	// --int ia=0;
	var ia = 0;
	// --int ib=0;
	var ib = 0;
	// --int ea=0;
	var ea = 0;
	// int eb=0;
	var eb = 0;
	// byte ca=0;
	var ca = 0;
	// --byte cb=0;
	var cb = 0;
	/* determine requested digits and form */
	if (set.lostDigits)
		this.checkdigits(rhs, set.digits);
	lhs = this; // name for clarity and proxy

	/* Quick exit for add floating 0 */
	// plus() will optimize to return same object if possible
	if (lhs.ind == 0)
		if (set.form != MathContext.prototype.PLAIN)
			return rhs.plus(set);
	if (rhs.ind == 0)
		if (set.form != MathContext.prototype.PLAIN)
			return lhs.plus(set);

	/* Prepare numbers (round, unless unlimited precision) */
	reqdig = set.digits; // local copy (heavily used)
	if (reqdig > 0) {
		if (lhs.mant.length > reqdig)
			lhs = this.clone(lhs).round(set);
		if (rhs.mant.length > reqdig)
			rhs = this.clone(rhs).round(set);
		// [we could reuse the new LHS for result in this case]
	}

	res = new BigDecimal(); // build result here

	/*
	 * Now see how much we have to pad or truncate lhs or rhs in order to align
	 * the numbers. If one number is much larger than the other, then the
	 * smaller cannot affect the answer [but we may still need to pad with up to
	 * DIGITS trailing zeros].
	 */
	// Note sign may be 0 if digits (reqdig) is 0
	// usel and user will be the byte arrays passed to the adder; we'll
	// use them on all paths except quick exits
	usel = lhs.mant;
	usellen = lhs.mant.length;
	user = rhs.mant;
	userlen = rhs.mant.length;
	{
		padder: do {/* select */
			if (lhs.exp == rhs.exp) {/* no padding needed */
				// This is the most common, and fastest, path
				res.exp = lhs.exp;
			} else if (lhs.exp > rhs.exp) { // need to pad lhs and/or truncate
				// rhs
				newlen = (usellen + lhs.exp) - rhs.exp;
				/*
				 * If, after pad, lhs would be longer than rhs by digits+1 or
				 * more (and digits>0) then rhs cannot affect answer, so we only
				 * need to pad up to a length of DIGITS+1.
				 */
				if (newlen >= ((userlen + reqdig) + 1))
					if (reqdig > 0) {
						// LHS is sufficient
						res.mant = usel;
						res.exp = lhs.exp;
						res.ind = lhs.ind;
						if (usellen < reqdig) { // need 0 padding
							res.mant = this.extend(lhs.mant, reqdig);
							res.exp = res.exp - ((reqdig - usellen));
						}
						return res.finish(set, false);
					}
				// RHS may affect result
				res.exp = rhs.exp; // expected final exponent
				if (newlen > (reqdig + 1))
					if (reqdig > 0) {
						// LHS will be max; RHS truncated
						tlen = (newlen - reqdig) - 1; // truncation length
						userlen = userlen - tlen;
						res.exp = res.exp + tlen;
						newlen = reqdig + 1;
					}
				if (newlen > usellen)
					usellen = newlen; // need to pad LHS
			} else { // need to pad rhs and/or truncate lhs
				newlen = (userlen + rhs.exp) - lhs.exp;
				if (newlen >= ((usellen + reqdig) + 1))
					if (reqdig > 0) {
						// RHS is sufficient
						res.mant = user;
						res.exp = rhs.exp;
						res.ind = rhs.ind;
						if (userlen < reqdig) { // need 0 padding
							res.mant = this.extend(rhs.mant, reqdig);
							res.exp = res.exp - ((reqdig - userlen));
						}
						return res.finish(set, false);
					}
				// LHS may affect result
				res.exp = lhs.exp; // expected final exponent
				if (newlen > (reqdig + 1))
					if (reqdig > 0) {
						// RHS will be max; LHS truncated
						tlen = (newlen - reqdig) - 1; // truncation length
						usellen = usellen - tlen;
						res.exp = res.exp + tlen;
						newlen = reqdig + 1;
					}
				if (newlen > userlen)
					userlen = newlen; // need to pad RHS
			}
		} while (false);
	}/* padder */

	/* OK, we have aligned mantissas. Now add or subtract. */
	// 1998.06.27 Sign may now be 0 [e.g., 0.000] .. treat as positive
	// 1999.05.27 Allow for 00 on lhs [is not larger than 2 on rhs]
	// 1999.07.10 Allow for 00 on rhs [is not larger than 2 on rhs]
	if (lhs.ind == this.iszero)
		res.ind = this.ispos;
	else
		res.ind = lhs.ind; // likely sign, all paths
	if (((lhs.ind == this.isneg) ? 1 : 0) == ((rhs.ind == this.isneg) ? 1 : 0)) // same
		// sign,
		// 0
		// non-negative
		mult = 1;
	else {
		signdiff: do { // different signs, so subtraction is needed
			mult = -1; // will cause subtract
			/*
			 * Before we can subtract we must determine which is the larger, as
			 * our add/subtract routine only handles non-negative results so we
			 * may need to swap the operands.
			 */
			{
				swaptest: do {/* select */
					if (rhs.ind == this.iszero)
						; // original A bigger
					else if ((usellen < userlen) || (lhs.ind == this.iszero)) { // original
						// B
						// bigger
						t = usel;
						usel = user;
						user = t; // swap
						tlen = usellen;
						usellen = userlen;
						userlen = tlen; // ..
						res.ind = -res.ind; // and set sign
					} else if (usellen > userlen)
						; // original A bigger
					else {
						{/* logical lengths the same */// need compare
							/* may still need to swap: compare the strings */
							ia = 0;
							ib = 0;
							ea = usel.length - 1;
							eb = user.length - 1;
							{
								compare: for (;;) {
									if (ia <= ea)
										ca = usel[ia];
									else {
										if (ib > eb) {/* identical */
											if (set.form != MathContext.prototype.PLAIN)
												return this.ZERO;
											// [if PLAIN we must do the
											// subtract, in case of 0.000
											// results]
											break compare;
										}
										ca = 0;
									}
									if (ib <= eb)
										cb = user[ib];
									else
										cb = 0;
									if (ca != cb) {
										if (ca < cb) {/* swap needed */
											t = usel;
											usel = user;
											user = t; // swap
											tlen = usellen;
											usellen = userlen;
											userlen = tlen; // ..
											res.ind = -res.ind;
										}
										break compare;
									}
									/* mantissas the same, so far */
									ia++;
									ib++;
								}
							}/* compare */
						} // lengths the same
					}
				} while (false);
			}/* swaptest */
		} while (false);
	}/* signdiff */

	/* here, A is > B if subtracting */
	// add [A+B*1] or subtract [A+(B*-1)]
	res.mant = this.byteaddsub(usel, usellen, user, userlen, mult, false);
	// [reuse possible only after chop; accounting makes not worthwhile]

	// Finish() rounds before stripping leading 0's, then sets form, etc.
	return res.finish(set, false);
}

function compareTo() {
	var set;
	if (compareTo.arguments.length == 2) {
		set = compareTo.arguments[1];
	} else if (compareTo.arguments.length == 1) {
		set = this.plainMC;
	} else {
		throw "compareTo(): " + compareTo.arguments.length
				+ " arguments given; expected 1 or 2"
	}
	var rhs = compareTo.arguments[0];
	// --int thislength=0;
	var thislength = 0;
	// --int i=0;
	var i = 0;
	// --com.ibm.icu.math.BigDecimal newrhs;
	var newrhs;
	// rhs=null will raise NullPointerException, as per Comparable interface
	if (set.lostDigits)
		this.checkdigits(rhs, set.digits);
	// [add will recheck in slowpath cases .. but would report -rhs]
	if ((this.ind == rhs.ind) && (this.exp == rhs.exp)) {
		/* sign & exponent the same [very common] */
		thislength = this.mant.length;
		if (thislength < rhs.mant.length)
			return -this.ind;
		if (thislength > rhs.mant.length)
			return this.ind;
		/*
		 * lengths are the same; we can do a straight mantissa compare unless
		 * maybe rounding [rounding is very unusual]
		 */
		if ((thislength <= set.digits) || (set.digits == 0)) {
			{
				var $6 = thislength;
				i = 0;
				i: for (; $6 > 0; $6--, i++) {
					if (this.mant[i] < rhs.mant[i])
						return -this.ind;
					if (this.mant[i] > rhs.mant[i])
						return this.ind;
				}
			}/* i */
			return 0; // identical
		}
		/* drop through for full comparison */
	} else {
		/* More fastpaths possible */
		if (this.ind < rhs.ind)
			return -1;
		if (this.ind > rhs.ind)
			return 1;
	}
	/* carry out a subtract to make the comparison */
	newrhs = this.clone(rhs); // safe copy
	newrhs.ind = -newrhs.ind; // prepare to subtract
	return this.add(newrhs, set).ind; // add, and return sign of result
}

function divide() {
	var set;
	var scale = -1;
	if (divide.arguments.length == 2) {
		if (typeof divide.arguments[1] == 'number') {
			set = new MathContext(0, MathContext.prototype.PLAIN, false,
					divide.arguments[1]); // [checks round, too]
		} else {
			set = divide.arguments[1];
		}
	} else if (divide.arguments.length == 3) {
		scale = divide.arguments[1];
		if (scale < 0)
			throw "divide(): Negative scale: " + scale;
		set = new MathContext(0, MathContext.prototype.PLAIN, false,
				divide.arguments[2]); // [checks round]
	} else if (divide.arguments.length == 1) {
		set = this.plainMC;
	} else {
		throw "divide(): " + divide.arguments.length
				+ " arguments given; expected between 1 and 3"
	}
	var rhs = divide.arguments[0];
	return this.dodivide('D', rhs, set, scale);
}

function divideInteger() {
	var set;
	if (divideInteger.arguments.length == 2) {
		set = divideInteger.arguments[1];
	} else if (divideInteger.arguments.length == 1) {
		set = this.plainMC;
	} else {
		throw "divideInteger(): " + divideInteger.arguments.length
				+ " arguments given; expected 1 or 2"
	}
	var rhs = divideInteger.arguments[0];
	// scale 0 to drop .000 when plain
	return this.dodivide('I', rhs, set, 0);
}

function max() {
	var set;
	if (max.arguments.length == 2) {
		set = max.arguments[1];
	} else if (max.arguments.length == 1) {
		set = this.plainMC;
	} else {
		throw "max(): " + max.arguments.length
				+ " arguments given; expected 1 or 2"
	}
	var rhs = max.arguments[0];
	if ((this.compareTo(rhs, set)) >= 0)
		return this.plus(set);
	else
		return rhs.plus(set);
}

function min() {
	var set;
	if (min.arguments.length == 2) {
		set = min.arguments[1];
	} else if (min.arguments.length == 1) {
		set = this.plainMC;
	} else {
		throw "min(): " + min.arguments.length
				+ " arguments given; expected 1 or 2"
	}
	var rhs = min.arguments[0];
	if ((this.compareTo(rhs, set)) <= 0)
		return this.plus(set);
	else
		return rhs.plus(set);
}

function multiply() {
	var set;
	if (multiply.arguments.length == 2) {
		set = multiply.arguments[1];
	} else if (multiply.arguments.length == 1) {
		set = this.plainMC;
	} else {
		throw "multiply(): " + multiply.arguments.length
				+ " arguments given; expected 1 or 2"
	}
	var rhs = multiply.arguments[0];
	// --com.ibm.icu.math.BigDecimal lhs;
	var lhs;
	// --int padding;
	var padding;
	// --int reqdig;
	var reqdig;
	// --byte multer[]=null;
	var multer = null;
	// --byte multand[]=null;
	var multand = null;
	// --int multandlen;
	var multandlen;
	// --int acclen=0;
	var acclen = 0;
	// --com.ibm.icu.math.BigDecimal res;
	var res;
	// --byte acc[];
	var acc;
	// --int n=0;
	var n = 0;
	// --byte mult=0;
	var mult = 0;
	if (set.lostDigits)
		this.checkdigits(rhs, set.digits);
	lhs = this; // name for clarity and proxy

	/* Prepare numbers (truncate, unless unlimited precision) */
	padding = 0; // trailing 0's to add
	reqdig = set.digits; // local copy
	if (reqdig > 0) {
		if (lhs.mant.length > reqdig)
			lhs = this.clone(lhs).round(set);
		if (rhs.mant.length > reqdig)
			rhs = this.clone(rhs).round(set);
		// [we could reuse the new LHS for result in this case]
	} else {/* unlimited */
		// fixed point arithmetic will want every trailing 0; we add these
		// after the calculation rather than before, for speed.
		if (lhs.exp > 0)
			padding = padding + lhs.exp;
		if (rhs.exp > 0)
			padding = padding + rhs.exp;
	}

	// For best speed, as in DMSRCN, we use the shorter number as the
	// multiplier and the longer as the multiplicand.
	// 1999.12.22: We used to special case when the result would fit in
	// a long, but with Java 1.3 this gave no advantage.
	if (lhs.mant.length < rhs.mant.length) {
		multer = lhs.mant;
		multand = rhs.mant;
	} else {
		multer = rhs.mant;
		multand = lhs.mant;
	}

	/* Calculate how long result byte array will be */
	multandlen = (multer.length + multand.length) - 1; // effective length
	// optimize for 75% of the cases where a carry is expected...
	if ((multer[0] * multand[0]) > 9)
		acclen = multandlen + 1;
	else
		acclen = multandlen;

	/* Now the main long multiplication loop */
	res = new BigDecimal(); // where we'll build result
	acc = this.createArrayWithZeros(acclen); // accumulator, all zeros
	// 1998.07.01: calculate from left to right so that accumulator goes
	// to likely final length on first addition; this avoids a one-digit
	// extension (and object allocation) each time around the loop.
	// Initial number therefore has virtual zeros added to right.
	{
		var $7 = multer.length;
		n = 0;
		n: for (; $7 > 0; $7--, n++) {
			mult = multer[n];
			if (mult != 0) { // [optimization]
				// accumulate [accumulator is reusable array]
				acc = this.byteaddsub(acc, acc.length, multand, multandlen,
						mult, true);
			}
			// divide multiplicand by 10 for next digit to right
			multandlen--; // 'virtual length'
		}
	}/* n */

	res.ind = lhs.ind * rhs.ind; // final sign
	res.exp = (lhs.exp + rhs.exp) - padding; // final exponent
	// [overflow is checked by finish]

	/* add trailing zeros to the result, if necessary */
	if (padding == 0)
		res.mant = acc;
	else
		res.mant = this.extend(acc, acc.length + padding); // add trailing 0s
	return res.finish(set, false);
}

function negate() {
	var set;
	if (negate.arguments.length == 1) {
		set = negate.arguments[0];
	} else if (negate.arguments.length == 0) {
		set = this.plainMC;
	} else {
		throw "negate(): " + negate.arguments.length
				+ " arguments given; expected 0 or 1"
	}
	// --com.ibm.icu.math.BigDecimal res;
	var res;
	// Originally called minus(), changed to matched Java precedents
	// This simply clones, flips the sign, and possibly rounds
	if (set.lostDigits)
		this.checkdigits(null, set.digits);
	res = this.clone(this); // safe copy
	res.ind = -res.ind;
	return res.finish(set, false);
}

function plus() {
	var set;
	if (plus.arguments.length == 1) {
		set = plus.arguments[0];
	} else if (plus.arguments.length == 0) {
		set = this.plainMC;
	} else {
		throw "plus(): " + plus.arguments.length
				+ " arguments given; expected 0 or 1"
	}
	// This clones and forces the result to the new settings
	// May return same object
	if (set.lostDigits)
		this.checkdigits(null, set.digits);
	// Optimization: returns same object for some common cases
	if (set.form == MathContext.prototype.PLAIN)
		if (this.form == MathContext.prototype.PLAIN) {
			if (this.mant.length <= set.digits)
				return this;
			if (set.digits == 0)
				return this;
		}
	return this.clone(this).finish(set, false);
}

function pow() {
	var set;
	if (pow.arguments.length == 2) {
		set = pow.arguments[1];
	} else if (pow.arguments.length == 1) {
		set = this.plainMC;
	} else {
		throw "pow(): " + pow.arguments.length
				+ " arguments given; expected 1 or 2"
	}
	var rhs = pow.arguments[0];
	// --int n;
	var n;
	// --com.ibm.icu.math.BigDecimal lhs;
	var lhs;
	// --int reqdig;
	var reqdig;
	// -- int workdigits=0;
	var workdigits = 0;
	// --int L=0;
	var L = 0;
	// --com.ibm.icu.math.MathContext workset;
	var workset;
	// --com.ibm.icu.math.BigDecimal res;
	var res;
	// --boolean seenbit;
	var seenbit;
	// --int i=0;
	var i = 0;
	if (set.lostDigits)
		this.checkdigits(rhs, set.digits);
	n = rhs.intcheck(this.MinArg, this.MaxArg); // check RHS by the rules
	lhs = this; // clarified name

	reqdig = set.digits; // local copy (heavily used)
	if (reqdig == 0) {
		if (rhs.ind == this.isneg)
			// --throw new java.lang.ArithmeticException("Negative power:"+"
			// "+rhs.toString());
			throw "pow(): Negative power: " + rhs.toString()
		workdigits = 0;
	} else {/* non-0 digits */
		if ((rhs.mant.length + rhs.exp) > reqdig)
			// --throw new java.lang.ArithmeticException("Too many digits:"+"
			// "+rhs.toString());
			throw "pow(): Too many digits: " + rhs.toString()

			/* Round the lhs to DIGITS if need be */
		if (lhs.mant.length > reqdig)
			lhs = this.clone(lhs).round(set);

		/* L for precision calculation [see ANSI X3.274-1996] */
		L = rhs.mant.length + rhs.exp; // length without decimal zeros/exp
		workdigits = (reqdig + L) + 1; // calculate the working DIGITS
	}

	/* Create a copy of set for working settings */
	// Note: no need to check for lostDigits again.
	// 1999.07.17 Note: this construction must follow RHS check
	workset = new MathContext(workdigits, set.form, false, set.roundingMode);

	res = this.ONE; // accumulator
	if (n == 0)
		return res; // x**0 == 1
	if (n < 0)
		n = -n; // [rhs.ind records the sign]
	seenbit = false; // set once we've seen a 1-bit
	{
		i = 1;
		i: for (;; i++) { // for each bit [top bit ignored]
			n = n + n; // shift left 1 bit
			if (n < 0) { // top bit is set
				seenbit = true; // OK, we're off
				res = res.multiply(lhs, workset); // acc=acc*x
			}
			if (i == 31)
				break i; // that was the last bit
			if ((!seenbit))
				continue i; // we don't have to square 1
			res = res.multiply(res, workset); // acc=acc*acc [square]
		}
	}/* i */// 32 bits
	if (rhs.ind < 0) // was a **-n [hence digits>0]
		res = this.ONE.divide(res, workset); // .. so acc=1/acc
	return res.finish(set, true); // round and strip [original digits]
}

/**
 * Returns a plain <code>BigDecimal</code> whose value is the remainder of
 * <code>this/rhs</code>, using fixed point arithmetic.
 * <p>
 * The same as {@link #remainder(BigDecimal, MathContext)}, where the
 * <code>BigDecimal</code> is <code>rhs</code>, and the context is
 * <code>new MathContext(0, MathContext.PLAIN)</code>.
 * <p>
 * This is not the modulo operator -- the result may be negative.
 * 
 * @param rhs
 *            The <code>BigDecimal</code> for the right hand side of the
 *            remainder operation.
 * @return A <code>BigDecimal</code> whose value is the remainder of
 *         <code>this/rhs</code>, using fixed point arithmetic.
 * @throws ArithmeticException
 *             if <code>rhs</code> is zero.
 * @stable ICU 2.0
 */

// --public com.ibm.icu.math.BigDecimal remainder(com.ibm.icu.math.BigDecimal
// rhs){
// -- return this.dodivide('R',rhs,plainMC,-1);
// -- }
/**
 * Returns a <code>BigDecimal</code> whose value is the remainder of
 * <code>this/rhs</code>.
 * <p>
 * Implements the remainder operator (as defined in the decimal documentation,
 * see {@link BigDecimal class header}), and returns the result as a
 * <code>BigDecimal</code> object.
 * <p>
 * This is not the modulo operator -- the result may be negative.
 * 
 * @param rhs
 *            The <code>BigDecimal</code> for the right hand side of the
 *            remainder operation.
 * @param set
 *            The <code>MathContext</code> arithmetic settings.
 * @return A <code>BigDecimal</code> whose value is the remainder of
 *         <code>this+rhs</code>.
 * @throws ArithmeticException
 *             if <code>rhs</code> is zero.
 * @throws ArithmeticException
 *             if the integer part of the result will not fit in the number of
 *             digits specified for the context.
 * @stable ICU 2.0
 */

// --public com.ibm.icu.math.BigDecimal remainder(com.ibm.icu.math.BigDecimal
// rhs,com.ibm.icu.math.MathContext set){
function remainder() {
	var set;
	if (remainder.arguments.length == 2) {
		set = remainder.arguments[1];
	} else if (remainder.arguments.length == 1) {
		set = this.plainMC;
	} else {
		throw "remainder(): " + remainder.arguments.length
				+ " arguments given; expected 1 or 2"
	}
	var rhs = remainder.arguments[0];
	return this.dodivide('R', rhs, set, -1);
}

function subtract() {
	var set;
	if (subtract.arguments.length == 2) {
		set = subtract.arguments[1];
	} else if (subtract.arguments.length == 1) {
		set = this.plainMC;
	} else {
		throw "subtract(): " + subtract.arguments.length
				+ " arguments given; expected 1 or 2"
	}
	var rhs = subtract.arguments[0];
	// --com.ibm.icu.math.BigDecimal newrhs;
	var newrhs;
	if (set.lostDigits)
		this.checkdigits(rhs, set.digits);
	// [add will recheck .. but would report -rhs]
	/* carry out the subtraction */
	// we could fastpath -0, but it is too rare.
	newrhs = this.clone(rhs); // safe copy
	newrhs.ind = -newrhs.ind; // prepare to subtract
	return this.add(newrhs, set); // arithmetic
}

function equals(obj) {
	// --com.ibm.icu.math.BigDecimal rhs;
	var rhs;
	// --int i=0;
	var i = 0;
	// --char lca[]=null;
	var lca = null;
	// --char rca[]=null;
	var rca = null;
	// We are equal iff toString of both are exactly the same
	if (obj == null)
		return false; // not equal
	if ((!(((obj instanceof BigDecimal)))))
		return false; // not a decimal
	rhs = obj; // cast; we know it will work
	if (this.ind != rhs.ind)
		return false; // different signs never match
	if (((this.mant.length == rhs.mant.length) && (this.exp == rhs.exp))
			&& (this.form == rhs.form))

	{ // mantissas say all
		// here with equal-length byte arrays to compare
		{
			var $8 = this.mant.length;
			i = 0;
			i: for (; $8 > 0; $8--, i++) {
				if (this.mant[i] != rhs.mant[i])
					return false;
			}
		}/* i */
	} else { // need proper layout
		lca = this.layout(); // layout to character array
		rca = rhs.layout();
		if (lca.length != rca.length)
			return false; // mismatch
		// here with equal-length character arrays to compare
		{
			var $9 = lca.length;
			i = 0;
			i: for (; $9 > 0; $9--, i++) {
				if (lca[i] != rca[i])
					return false;
			}
		}/* i */
	}
	return true; // arrays have identical content
}

function format() {
	var explaces;
	var exdigits;
	var exformint;
	var exround;
	if (format.arguments.length == 6) {
		explaces = format.arguments[2];
		exdigits = format.arguments[3];
		exformint = format.arguments[4];
		exround = format.arguments[5];
	} else if (format.arguments.length == 2) {
		explaces = -1;
		exdigits = -1;
		exformint = MathContext.prototype.SCIENTIFIC;
		exround = this.ROUND_HALF_UP;
	} else {
		throw "format(): " + format.arguments.length
				+ " arguments given; expected 2 or 6"
	}
	var before = format.arguments[0];
	var after = format.arguments[1];
	// --com.ibm.icu.math.BigDecimal num;
	var num;
	// --int mag=0;
	var mag = 0;
	// --int thisafter=0;
	var thisafter = 0;
	// --int lead=0;
	var lead = 0;
	// --byte newmant[]=null;
	var newmant = null;
	// --int chop=0;
	var chop = 0;
	// --int need=0;
	var need = 0;
	// --int oldexp=0;
	var oldexp = 0;
	// --char a[];
	var a;
	// --int p=0;
	var p = 0;
	// --char newa[]=null;
	var newa = null;
	// --int i=0;
	var i = 0;
	// --int places=0;
	var places = 0;

	/* Check arguments */
	if ((before < (-1)) || (before == 0))
		this.badarg("format", 1, before);
	if (after < (-1))
		this.badarg("format", 2, after);
	if ((explaces < (-1)) || (explaces == 0))
		this.badarg("format", 3, explaces);
	if (exdigits < (-1))
		this.badarg("format", 4, exdigits);
	{/* select */
		if (exformint == MathContext.prototype.SCIENTIFIC)
			;
		else if (exformint == MathContext.prototype.ENGINEERING)
			;
		else if (exformint == (-1))
			exformint = MathContext.prototype.SCIENTIFIC;
		// note PLAIN isn't allowed
		else {
			this.badarg("format", 5, exformint);
		}
	}
	// checking the rounding mode is done by trying to construct a
	// MathContext object with that mode; it will fail if bad
	if (exround != this.ROUND_HALF_UP) {
		try { // if non-default...
			if (exround == (-1))
				exround = this.ROUND_HALF_UP;
			else
				new MathContext(9, MathContext.prototype.SCIENTIFIC, false,
						exround);
		} catch ($10) {
			this.badarg("format", 6, exround);
		}
	}

	num = this.clone(this); // make private copy

	/*
	 * Here: num is BigDecimal to format before is places before point [>0]
	 * after is places after point [>=0] explaces is exponent places [>0]
	 * exdigits is exponent digits [>=0] exformint is exponent form [one of two]
	 * exround is rounding mode [one of eight] 'before' through 'exdigits' are
	 * -1 if not specified
	 */

	/* determine form */
	{
		setform: do {/* select */
			if (exdigits == (-1))
				num.form = MathContext.prototype.PLAIN;
			else if (num.ind == this.iszero)
				num.form = MathContext.prototype.PLAIN;
			else {
				// determine whether triggers
				mag = num.exp + num.mant.length;
				if (mag > exdigits)
					num.form = exformint;
				else if (mag < (-5))
					num.form = exformint;
				else
					num.form = MathContext.prototype.PLAIN;
			}
		} while (false);
	}/* setform */

	/*
	 * If 'after' was specified then we may need to adjust the mantissa. This is
	 * a little tricky, as we must conform to the rules of exponential layout if
	 * necessary (e.g., we cannot end up with 10.0 if scientific).
	 */
	if (after >= 0) {
		setafter: for (;;) {
			// calculate the current after-length
			{/* select */
				if (num.form == MathContext.prototype.PLAIN)
					thisafter = -num.exp; // has decimal part
				else if (num.form == MathContext.prototype.SCIENTIFIC)
					thisafter = num.mant.length - 1;
				else { // engineering
					lead = (((num.exp + num.mant.length) - 1)) % 3; // exponent
					// to use
					if (lead < 0)
						lead = 3 + lead; // negative exponent case
					lead++; // number of leading digits
					if (lead >= num.mant.length)
						thisafter = 0;
					else
						thisafter = num.mant.length - lead;
				}
			}
			if (thisafter == after)
				break setafter; // we're in luck
			if (thisafter < after) { // need added trailing zeros
				// [thisafter can be negative]
				newmant = this.extend(num.mant, (num.mant.length + after)
						- thisafter);
				num.mant = newmant;
				num.exp = num.exp - ((after - thisafter)); // adjust exponent
				if (num.exp < this.MinExp)
					throw "format(): Exponent Overflow: " + num.exp;
				break setafter;
			}
			// We have too many digits after the decimal point; this could
			// cause a carry, which could change the mantissa...
			// Watch out for implied leading zeros in PLAIN case
			chop = thisafter - after; // digits to lop [is >0]
			if (chop > num.mant.length) { // all digits go, no chance of carry
				// carry on with zero
				num.mant = this.ZERO.mant;
				num.ind = this.iszero;
				num.exp = 0;
				continue setafter; // recheck: we may need trailing zeros
			}
			// we have a digit to inspect from existing mantissa
			// round the number as required
			need = num.mant.length - chop; // digits to end up with [may be 0]
			oldexp = num.exp; // save old exponent
			num.round(need, exround);
			// if the exponent grew by more than the digits we chopped, then
			// we must have had a carry, so will need to recheck the layout
			if ((num.exp - oldexp) == chop)
				break setafter; // number did not have carry
			// mantissa got extended .. so go around and check again
		}
	}/* setafter */

	a = num.layout(); // lay out, with exponent if required, etc.

	/* Here we have laid-out number in 'a' */
	// now apply 'before' and 'explaces' as needed
	if (before > 0) {
		// look for '.' or 'E'
		{
			var $11 = a.length;
			p = 0;
			p: for (; $11 > 0; $11--, p++) {
				if (a[p] == '.')
					break p;
				if (a[p] == 'E')
					break p;
			}
		}/* p */
		// p is now offset of '.', 'E', or character after end of array
		// that is, the current length of before part
		if (p > before)
			this.badarg("format", 1, before); // won't fit
		if (p < before) { // need leading blanks
			newa = new Array((a.length + before) - p);
			{
				var $12 = before - p;
				i = 0;
				i: for (; $12 > 0; $12--, i++) {
					newa[i] = ' ';
				}
			}/* i */
			// --java.lang.System.arraycopy((java.lang.Object)a,0,(java.lang.Object)newa,i,a.length);
			this.arraycopy(a, 0, newa, i, a.length);
			a = newa;
		}
		// [if p=before then it's just the right length]
	}

	if (explaces > 0) {
		// look for 'E' [cannot be at offset 0]
		{
			var $13 = a.length - 1;
			p = a.length - 1;
			p: for (; $13 > 0; $13--, p--) {
				if (a[p] == 'E')
					break p;
			}
		}/* p */
		// p is now offset of 'E', or 0
		if (p == 0) { // no E part; add trailing blanks
			newa = new Array((a.length + explaces) + 2);
			// --java.lang.System.arraycopy((java.lang.Object)a,0,(java.lang.Object)newa,0,a.length);
			this.arraycopy(a, 0, newa, 0, a.length);
			{
				var $14 = explaces + 2;
				i = a.length;
				i: for (; $14 > 0; $14--, i++) {
					newa[i] = ' ';
				}
			}/* i */
			a = newa;
		} else {/* found E */// may need to insert zeros
			places = (a.length - p) - 2; // number so far
			if (places > explaces)
				this.badarg("format", 3, explaces);
			if (places < explaces) { // need to insert zeros
				newa = new Array((a.length + explaces) - places);
				// --java.lang.System.arraycopy((java.lang.Object)a,0,(java.lang.Object)newa,0,p+2);
				// // through E and sign
				this.arraycopy(a, 0, newa, 0, p + 2);
				{
					var $15 = explaces - places;
					i = p + 2;
					i: for (; $15 > 0; $15--, i++) {
						newa[i] = '0';
					}
				}/* i */
				// --java.lang.System.arraycopy((java.lang.Object)a,p+2,(java.lang.Object)newa,i,places);
				// // remainder of exponent
				this.arraycopy(a, p + 2, newa, i, places);
				a = newa;
			}
			// [if places=explaces then it's just the right length]
		}
	}
	return a.join("");
}

function intValueExact() {
	// --int lodigit;
	var lodigit;
	// --int useexp=0;
	var useexp = 0;
	// --int result;
	var result;
	// --int i=0;
	var i = 0;
	// --int topdig=0;
	var topdig = 0;
	// This does not use longValueExact() as the latter can be much
	// slower.
	// intcheck (from pow) relies on this to check decimal part
	if (this.ind == this.iszero)
		return 0; // easy, and quite common
	/* test and drop any trailing decimal part */
	lodigit = this.mant.length - 1;
	if (this.exp < 0) {
		lodigit = lodigit + this.exp; // reduces by -(-exp)
		/* all decimal places must be 0 */
		if ((!(this.allzero(this.mant, lodigit + 1))))
			throw "intValueExact(): Decimal part non-zero: " + this.toString();
		if (lodigit < 0)
			return 0; // -1<this<1
		useexp = 0;
	} else {/* >=0 */
		if ((this.exp + lodigit) > 9) // early exit
			throw "intValueExact(): Conversion overflow: " + this.toString();
		useexp = this.exp;
	}
	/* convert the mantissa to binary, inline for speed */
	result = 0;
	{
		var $16 = lodigit + useexp;
		i = 0;
		i: for (; i <= $16; i++) {
			result = result * 10;
			if (i <= lodigit)
				result = result + this.mant[i];
		}
	}/* i */

	/* Now, if the risky length, check for overflow */
	if ((lodigit + useexp) == 9) {
		// note we cannot just test for -ve result, as overflow can move a
		// zero into the top bit [consider 5555555555]
		topdig = div(result, 1000000000); // get top digit, preserving sign
		if (topdig != this.mant[0]) { // digit must match and be positive
			// except in the special case ...
			if (result == -2147483648) // looks like the special
				if (this.ind == this.isneg) // really was negative
					if (this.mant[0] == 2)
						return result; // really had top digit 2
			throw "intValueExact(): Conversion overflow: " + this.toString();
		}
	}

	/* Looks good */
	if (this.ind == this.ispos)
		return result;
	return -result;
}

function movePointLeft(n) {
	// --com.ibm.icu.math.BigDecimal res;
	var res;
	// very little point in optimizing for shift of 0
	res = this.clone(this);
	res.exp = res.exp - n;
	return res.finish(this.plainMC, false); // finish sets form and checks
	// exponent
}

function movePointRight(n) {
	// --com.ibm.icu.math.BigDecimal res;
	var res;
	res = this.clone(this);
	res.exp = res.exp + n;
	return res.finish(this.plainMC, false);
}

function scale() {
	if (this.exp >= 0)
		return 0; // scale can never be negative
	return -this.exp;
}

function setScale() {
	var round;
	if (setScale.arguments.length == 2) {
		round = setScale.arguments[1];
	} else if (setScale.arguments.length == 1) {
		round = this.ROUND_UNNECESSARY;
	} else {
		throw "setScale(): " + setScale.arguments.length
				+ " given; expected 1 or 2"
	}
	var scale = setScale.arguments[0];
	// --int ourscale;
	var ourscale;
	// --com.ibm.icu.math.BigDecimal res;
	var res;
	// --int padding=0;
	var padding = 0;
	// --int newlen=0;
	var newlen = 0;
	// at present this naughtily only checks the round value if it is
	// needed (used), for speed
	ourscale = this.scale();
	if (ourscale == scale) // already correct scale
		if (this.form == MathContext.prototype.PLAIN) // .. and form
			return this;
	res = this.clone(this); // need copy
	if (ourscale <= scale) { // simply zero-padding/changing form
		// if ourscale is 0 we may have lots of 0s to add
		if (ourscale == 0)
			padding = res.exp + scale;
		else
			padding = scale - ourscale;
		res.mant = this.extend(res.mant, res.mant.length + padding);
		res.exp = -scale; // as requested
	} else {/* ourscale>scale: shortening, probably */
		if (scale < 0)
			// --throw new java.lang.ArithmeticException("Negative scale:"+"
			// "+scale);
			throw "setScale(): Negative scale: " + scale;
		// [round() will raise exception if invalid round]
		newlen = res.mant.length - ((ourscale - scale)); // [<=0 is OK]
		res = res.round(newlen, round); // round to required length
		// This could have shifted left if round (say) 0.9->1[.0]
		// Repair if so by adding a zero and reducing exponent
		if (res.exp != (-scale)) {
			res.mant = this.extend(res.mant, res.mant.length + 1);
			res.exp = res.exp - 1;
		}
	}
	res.form = MathContext.prototype.PLAIN; // by definition
	return res;
}

function signum() {
	return this.ind; // [note this assumes values for ind.]
}

function toString() {
	return this.layout().join("");
}

function layout() {
	// --char cmant[];
	var cmant;
	// --int i=0;
	var i = 0;
	// --java.lang.StringBuffer sb=null;
	var sb = null;
	// --int euse=0;
	var euse = 0;
	// --int sig=0;
	var sig = 0;
	// --char csign=0;
	var csign = 0;
	// --char rec[]=null;
	var rec = null;
	// --int needsign;
	var needsign;
	// --int mag;
	var mag;
	// --int len=0;
	var len = 0;
	cmant = new Array(this.mant.length); // copy byte[] to a char[]
	{
		var $18 = this.mant.length;
		i = 0;
		i: for (; $18 > 0; $18--, i++) {
			cmant[i] = this.mant[i] + '';
		}
	}/* i */

	if (this.form != MathContext.prototype.PLAIN) {/*
													 * exponential notation
													 * needed
													 */
		// --sb=new java.lang.StringBuffer(cmant.length+15); //
		// -x.xxxE+999999999
		sb = "";
		if (this.ind == this.isneg)
			sb += '-';
		euse = (this.exp + cmant.length) - 1; // exponent to use
		/* setup sig=significant digits and copy to result */
		if (this.form == MathContext.prototype.SCIENTIFIC) { // [default]
			sb += cmant[0]; // significant character
			if (cmant.length > 1) // have decimal part
				// --sb.append('.').append(cmant,1,cmant.length-1);
				sb += '.';
			sb += cmant.slice(1).join("");
		} else {
			engineering: do {
				sig = euse % 3; // common
				if (sig < 0)
					sig = 3 + sig; // negative exponent
				euse = euse - sig;
				sig++;
				if (sig >= cmant.length) { // zero padding may be needed
					// --sb.append(cmant,0,cmant.length);
					sb += cmant.join("");
					{
						var $19 = sig - cmant.length;
						for (; $19 > 0; $19--) {
							sb += '0';
						}
					}
				} else { // decimal point needed
					// --sb.append(cmant,0,sig).append('.').append(cmant,sig,cmant.length-sig);
					sb += cmant.slice(0, sig).join("");
					sb += '.';
					sb += cmant.slice(sig).join("");
				}
			} while (false);
		}/* engineering */
		if (euse != 0) {
			if (euse < 0) {
				csign = '-';
				euse = -euse;
			} else
				csign = '+';
			// --sb.append('E').append(csign).append(euse);
			sb += 'E';
			sb += csign;
			sb += euse;
		}
		// --rec=new Array(sb.length);
		// --Utility.getChars(sb, 0,sb.length(),rec,0);
		// --return rec;
		return sb.split("");
	}

	/* Here for non-exponential (plain) notation */
	if (this.exp == 0) {/* easy */
		if (this.ind >= 0)
			return cmant; // non-negative integer
		rec = new Array(cmant.length + 1);
		rec[0] = '-';
		// --java.lang.System.arraycopy((java.lang.Object)cmant,0,(java.lang.Object)rec,1,cmant.length);
		this.arraycopy(cmant, 0, rec, 1, cmant.length);
		return rec;
	}

	/* Need a '.' and/or some zeros */
	needsign = ((this.ind == this.isneg) ? 1 : 0); // space for sign? 0 or 1

	/*
	 * MAG is the position of the point in the mantissa (index of the character
	 * it follows)
	 */
	mag = this.exp + cmant.length;

	if (mag < 1) {/* 0.00xxxx form */
		len = (needsign + 2) - this.exp; // needsign+2+(-mag)+cmant.length
		rec = new Array(len);
		if (needsign != 0)
			rec[0] = '-';
		rec[needsign] = '0';
		rec[needsign + 1] = '.';
		{
			var $20 = -mag;
			i = needsign + 2;
			i: for (; $20 > 0; $20--, i++) { // maybe none
				rec[i] = '0';
			}
		}/* i */
		// --java.lang.System.arraycopy((java.lang.Object)cmant,0,(java.lang.Object)rec,(needsign+2)-mag,cmant.length);
		this.arraycopy(cmant, 0, rec, (needsign + 2) - mag, cmant.length);
		return rec;
	}

	if (mag > cmant.length) {/* xxxx0000 form */
		len = needsign + mag;
		rec = new Array(len);
		if (needsign != 0)
			rec[0] = '-';
		// --java.lang.System.arraycopy((java.lang.Object)cmant,0,(java.lang.Object)rec,needsign,cmant.length);
		this.arraycopy(cmant, 0, rec, needsign, cmant.length);
		{
			var $21 = mag - cmant.length;
			i = needsign + cmant.length;
			i: for (; $21 > 0; $21--, i++) { // never 0
				rec[i] = '0';
			}
		}/* i */
		return rec;
	}

	/* decimal point is in the middle of the mantissa */
	len = (needsign + 1) + cmant.length;
	rec = new Array(len);
	if (needsign != 0)
		rec[0] = '-';
	// --java.lang.System.arraycopy((java.lang.Object)cmant,0,(java.lang.Object)rec,needsign,mag);
	this.arraycopy(cmant, 0, rec, needsign, mag);
	rec[needsign + mag] = '.';
	// --java.lang.System.arraycopy((java.lang.Object)cmant,mag,(java.lang.Object)rec,(needsign+mag)+1,cmant.length-mag);
	this.arraycopy(cmant, mag, rec, (needsign + mag) + 1, cmant.length - mag);
	return rec;
}

function intcheck(min, max) {
	// --int i;
	var i;
	i = this.intValueExact(); // [checks for non-0 decimal part]
	// Use same message as though intValueExact failed due to size
	if ((i < min) || (i > max))
		throw "intcheck(): Conversion overflow: " + i;
	return i;
}

function dodivide(code, rhs, set, scale) {
	// --com.ibm.icu.math.BigDecimal lhs;
	var lhs;
	// --int reqdig;
	var reqdig;
	// --int newexp;
	var newexp;
	// --com.ibm.icu.math.BigDecimal res;
	var res;
	// --int newlen;
	var newlen;
	// --byte var1[];
	var var1;
	// --int var1len;
	var var1len;
	// --byte var2[];
	var var2;
	// --int var2len;
	var var2len;
	// --int b2b;
	var b2b;
	// --int have;
	var have;
	// --int thisdigit=0;
	var thisdigit = 0;
	// --int i=0;
	var i = 0;
	// --byte v2=0;
	var v2 = 0;
	// --int ba=0;
	var ba = 0;
	// --int mult=0;
	var mult = 0;
	// --int start=0;
	var start = 0;
	// --int padding=0;
	var padding = 0;
	// --int d=0;
	var d = 0;
	// --byte newvar1[]=null;
	var newvar1 = null;
	// --byte lasthave=0;
	var lasthave = 0;
	// --int actdig=0;
	var actdig = 0;
	// --byte newmant[]=null;
	var newmant = null;

	if (set.lostDigits)
		this.checkdigits(rhs, set.digits);
	lhs = this; // name for clarity

	// [note we must have checked lostDigits before the following checks]
	if (rhs.ind == 0)
		throw "dodivide(): Divide by 0"; // includes 0/0
	if (lhs.ind == 0) { // 0/x => 0 [possibly with .0s]
		if (set.form != MathContext.prototype.PLAIN)
			return this.ZERO;
		if (scale == (-1))
			return lhs;
		return lhs.setScale(scale);
	}

	/* Prepare numbers according to BigDecimal rules */
	reqdig = set.digits; // local copy (heavily used)
	if (reqdig > 0) {
		if (lhs.mant.length > reqdig)
			lhs = this.clone(lhs).round(set);
		if (rhs.mant.length > reqdig)
			rhs = this.clone(rhs).round(set);
	} else {/* scaled divide */
		if (scale == (-1))
			scale = lhs.scale();
		// set reqdig to be at least large enough for the computation
		reqdig = lhs.mant.length; // base length
		// next line handles both positive lhs.exp and also scale mismatch
		if (scale != (-lhs.exp))
			reqdig = (reqdig + scale) + lhs.exp;
		reqdig = (reqdig - ((rhs.mant.length - 1))) - rhs.exp; // reduce by RHS
		// effect
		if (reqdig < lhs.mant.length)
			reqdig = lhs.mant.length; // clamp
		if (reqdig < rhs.mant.length)
			reqdig = rhs.mant.length; // ..
	}

	/* precalculate exponent */
	newexp = ((lhs.exp - rhs.exp) + lhs.mant.length) - rhs.mant.length;
	/* If new exponent -ve, then some quick exits are possible */
	if (newexp < 0)
		if (code != 'D') {
			if (code == 'I')
				return this.ZERO; // easy - no integer part
			/* Must be 'R'; remainder is [finished clone of] input value */
			return this.clone(lhs).finish(set, false);
		}

	/* We need slow division */
	res = new BigDecimal(); // where we'll build result
	res.ind = (lhs.ind * rhs.ind); // final sign (for D/I)
	res.exp = newexp; // initial exponent (for D/I)
	res.mant = this.createArrayWithZeros(reqdig + 1); // where build the
	// result

	/* Now [virtually pad the mantissae with trailing zeros */
	// Also copy the LHS, which will be our working array
	newlen = (reqdig + reqdig) + 1;
	var1 = this.extend(lhs.mant, newlen); // always makes longer, so new safe
	// array
	var1len = newlen; // [remaining digits are 0]

	var2 = rhs.mant;
	var2len = newlen;

	/* Calculate first two digits of rhs (var2), +1 for later estimations */
	b2b = (var2[0] * 10) + 1;
	if (var2.length > 1)
		b2b = b2b + var2[1];

	/* start the long-division loops */
	have = 0;
	{
		outer: for (;;) {
			thisdigit = 0;
			/* find the next digit */
			{
				inner: for (;;) {
					if (var1len < var2len)
						break inner; // V1 too low
					if (var1len == var2len) { // compare needed
						{
							compare: do { // comparison
								{
									var $22 = var1len;
									i = 0;
									i: for (; $22 > 0; $22--, i++) {
										// var1len is always <= var1.length
										if (i < var2.length)
											v2 = var2[i];
										else
											v2 = 0;
										if (var1[i] < v2)
											break inner; // V1 too low
										if (var1[i] > v2)
											break compare; // OK to subtract
									}
								}/* i */
								/*
								 * reach here if lhs and rhs are identical;
								 * subtraction will increase digit by one, and
								 * the residue will be 0 so we are done; leave
								 * the loop with residue set to 0 (in case code
								 * is 'R' or ROUND_UNNECESSARY or a
								 * ROUND_HALF_xxxx is being checked)
								 */
								thisdigit++;
								res.mant[have] = thisdigit;
								have++;
								var1[0] = 0; // residue to 0 [this is all
								// we'll test]
								// var1len=1 -- [optimized out]
								break outer;
							} while (false);
						}/* compare */
						/*
						 * prepare for subtraction. Estimate BA (lengths the
						 * same)
						 */
						ba = var1[0]; // use only first digit
					} // lengths the same
					else {/* lhs longer than rhs */
						/* use first two digits for estimate */
						ba = var1[0] * 10;
						if (var1len > 1)
							ba = ba + var1[1];
					}
					/* subtraction needed; V1>=V2 */
					mult = div((ba * 10), b2b);
					if (mult == 0)
						mult = 1;
					thisdigit = thisdigit + mult;
					// subtract; var1 reusable
					var1 = this.byteaddsub(var1, var1len, var2, var2len, -mult,
							true);
					if (var1[0] != 0)
						continue inner; // maybe another subtract needed
					/*
					 * V1 now probably has leading zeros, remove leading 0's and
					 * try again. (It could be longer than V2)
					 */
					{
						var $23 = var1len - 2;
						start = 0;
						start: for (; start <= $23; start++) {
							if (var1[start] != 0)
								break start;
							var1len--;
						}
					}/* start */
					if (start == 0)
						continue inner;
					// shift left
					// --java.lang.System.arraycopy((java.lang.Object)var1,start,(java.lang.Object)var1,0,var1len);
					this.arraycopy(var1, start, var1, 0, var1len);
				}
			}/* inner */

			/* We have the next digit */
			if ((have != 0) || (thisdigit != 0)) { // put the digit we got
				res.mant[have] = thisdigit;
				have++;
				if (have == (reqdig + 1))
					break outer; // we have all we need
				if (var1[0] == 0)
					break outer; // residue now 0
			}
			/* can leave now if a scaled divide and exponent is small enough */
			if (scale >= 0)
				if ((-res.exp) > scale)
					break outer;
			/* can leave now if not Divide and no integer part left */
			if (code != 'D')
				if (res.exp <= 0)
					break outer;
			res.exp = res.exp - 1; // reduce the exponent
			/*
			 * to get here, V1 is less than V2, so divide V2 by 10 and go for
			 * the next digit
			 */
			var2len--;
		}
	}/* outer */

	/* here when we have finished dividing, for some reason */
	// have is the number of digits we collected in res.mant
	if (have == 0)
		have = 1; // res.mant[0] is 0; we always want a digit

	if ((code == 'I') || (code == 'R')) {/* check for integer overflow needed */
		if ((have + res.exp) > reqdig)
			throw "dodivide(): Integer overflow";

		if (code == 'R') {
			remainder: do {
				/* We were doing Remainder -- return the residue */
				if (res.mant[0] == 0) // no integer part was found
					return this.clone(lhs).finish(set, false); // .. so return
				// lhs,
				// canonical
				if (var1[0] == 0)
					return this.ZERO; // simple 0 residue
				res.ind = lhs.ind; // sign is always as LHS
				/*
				 * Calculate the exponent by subtracting the number of padding
				 * zeros we added and adding the original exponent
				 */
				padding = ((reqdig + reqdig) + 1) - lhs.mant.length;
				res.exp = (res.exp - padding) + lhs.exp;

				/*
				 * strip insignificant padding zeros from residue, and
				 * create/copy the resulting mantissa if need be
				 */
				d = var1len;
				{
					i = d - 1;
					i: for (; i >= 1; i--) {
						if (!((res.exp < lhs.exp) && (res.exp < rhs.exp)))
							break;
						if (var1[i] != 0)
							break i;
						d--;
						res.exp = res.exp + 1;
					}
				}/* i */
				if (d < var1.length) {/* need to reduce */
					newvar1 = new Array(d);
					// --java.lang.System.arraycopy((java.lang.Object)var1,0,(java.lang.Object)newvar1,0,d);
					// // shorten
					this.arraycopy(var1, 0, newvar1, 0, d);
					var1 = newvar1;
				}
				res.mant = var1;
				return res.finish(set, false);
			} while (false);
		}/* remainder */
	}

	else {/* 'D' -- no overflow check needed */
		// If there was a residue then bump the final digit (iff 0 or 5)
		// so that the residue is visible for ROUND_UP, ROUND_HALF_xxx and
		// ROUND_UNNECESSARY checks (etc.) later.
		// [if we finished early, the residue will be 0]
		if (var1[0] != 0) { // residue not 0
			lasthave = res.mant[have - 1];
			if (((lasthave % 5)) == 0)
				res.mant[have - 1] = (lasthave + 1);
		}
	}

	/* Here for Divide or Integer Divide */
	// handle scaled results first ['I' always scale 0, optional for 'D']
	if (scale >= 0) {
		scaled: do {
			// say 'scale have res.exp len' scale have res.exp res.mant.length
			if (have != res.mant.length)
				// already padded with 0's, so just adjust exponent
				res.exp = res.exp - ((res.mant.length - have));
			// calculate number of digits we really want [may be 0]
			actdig = res.mant.length - (((-res.exp) - scale));
			res.round(actdig, set.roundingMode); // round to desired length
			// This could have shifted left if round (say) 0.9->1[.0]
			// Repair if so by adding a zero and reducing exponent
			if (res.exp != (-scale)) {
				res.mant = this.extend(res.mant, res.mant.length + 1);
				res.exp = res.exp - 1;
			}
			return res.finish(set, true); // [strip if not PLAIN]
		} while (false);
	}/* scaled */

	// reach here only if a non-scaled
	if (have == res.mant.length) { // got digits+1 digits
		res.round(set);
		have = reqdig;
	} else {/* have<=reqdig */
		if (res.mant[0] == 0)
			return this.ZERO; // fastpath
		// make the mantissa truly just 'have' long
		// [we could let finish do this, during strip, if we adjusted
		// the exponent; however, truncation avoids the strip loop]
		newmant = new Array(have); // shorten
		// --java.lang.System.arraycopy((java.lang.Object)res.mant,0,(java.lang.Object)newmant,0,have);
		this.arraycopy(res.mant, 0, newmant, 0, have);
		res.mant = newmant;
	}
	return res.finish(set, true);
}

/* <sgml> Report a conversion exception. </sgml> */

// --private void bad(char s[]){
function bad(prefix, s) {
	throw prefix + "Not a number: " + s;
}

function badarg(name, pos, value) {
	throw "Bad argument " + pos + " to " + name + ": " + value;
}

function extend(inarr, newlen) {
	// --byte newarr[];
	var newarr;
	if (inarr.length == newlen)
		return inarr;
	newarr = createArrayWithZeros(newlen);
	// --java.lang.System.arraycopy((java.lang.Object)inarr,0,(java.lang.Object)newarr,0,inarr.length);
	this.arraycopy(inarr, 0, newarr, 0, inarr.length);
	// 0 padding is carried out by the JVM on allocation initialization
	return newarr;
}

function byteaddsub(a, avlen, b, bvlen, m, reuse) {
	// --int alength;
	var alength;
	// --int blength;
	var blength;
	// --int ap;
	var ap;
	// --int bp;
	var bp;
	// --int maxarr;
	var maxarr;
	// --byte reb[];
	var reb;
	// --boolean quickm;
	var quickm;
	// --int digit;
	var digit;
	// --int op=0;
	var op = 0;
	// --int dp90=0;
	var dp90 = 0;
	// --byte newarr[];
	var newarr;
	// --int i=0;
	var i = 0;

	// We'll usually be right if we assume no carry
	alength = a.length; // physical lengths
	blength = b.length; // ..
	ap = avlen - 1; // -> final (rightmost) digit
	bp = bvlen - 1; // ..
	maxarr = bp;
	if (maxarr < ap)
		maxarr = ap;
	reb = null; // result byte array
	if (reuse)
		if ((maxarr + 1) == alength)
			reb = a; // OK to reuse A
	if (reb == null) {
		reb = this.createArrayWithZeros(maxarr + 1); // need new array
	}

	quickm = false; // 1 if no multiply needed
	if (m == 1)
		quickm = true; // most common
	else if (m == (-1))
		quickm = true; // also common

	digit = 0; // digit, with carry or borrow
	{
		op = maxarr;
		op: for (; op >= 0; op--) {
			if (ap >= 0) {
				if (ap < alength)
					digit = digit + a[ap]; // within A
				ap--;
			}
			if (bp >= 0) {
				if (bp < blength) { // within B
					if (quickm) {
						if (m > 0)
							digit = digit + b[bp]; // most common
						else
							digit = digit - b[bp]; // also common
					} else
						digit = digit + (b[bp] * m);
				}
				bp--;
			}
			/* result so far (digit) could be -90 through 99 */
			if (digit < 10)
				if (digit >= 0) {
					quick: do { // 0-9
						reb[op] = digit;
						digit = 0; // no carry
						continue op;
					} while (false);
				}/* quick */
			dp90 = digit + 90;
			reb[op] = this.bytedig[dp90]; // this digit
			digit = this.bytecar[dp90]; // carry or borrow
		}
	}/* op */

	if (digit == 0)
		return reb; // no carry
	// following line will become an Assert, later
	// if digit<0 then signal ArithmeticException("internal.error ["digit"]")

	/* We have carry -- need to make space for the extra digit */
	newarr = null;
	if (reuse)
		if ((maxarr + 2) == a.length)
			newarr = a; // OK to reuse A
	if (newarr == null)
		newarr = new Array(maxarr + 2);
	newarr[0] = digit; // the carried digit ..
	// .. and all the rest [use local loop for short numbers]
	// --if (maxarr<10)
	{
		var $24 = maxarr + 1;
		i = 0;
		i: for (; $24 > 0; $24--, i++) {
			newarr[i + 1] = reb[i];
		}
	}/* i */
	// --else
	// --java.lang.System.arraycopy((java.lang.Object)reb,0,(java.lang.Object)newarr,1,maxarr+1);
	return newarr;
}

function diginit() {
	// --byte work[];
	var work;
	// --int op=0;
	var op = 0;
	// --int digit=0;
	var digit = 0;
	work = new Array((90 + 99) + 1);
	{
		op = 0;
		op: for (; op <= (90 + 99); op++) {
			digit = op - 90;
			if (digit >= 0) {
				work[op] = (digit % 10);
				BigDecimal.prototype.bytecar[op] = (div(digit, 10)); // calculate
				// carry
				continue op;
			}
			// borrowing...
			digit = digit + 100; // yes, this is right [consider -50]
			work[op] = (digit % 10);
			BigDecimal.prototype.bytecar[op] = ((div(digit, 10)) - 10); // calculate
			// borrow
			// [NB:
			// -
			// after
			// %]
		}
	}/* op */
	return work;
}

function clone(dec) {
	// --com.ibm.icu.math.BigDecimal copy;
	var copy;
	copy = new BigDecimal();
	copy.ind = dec.ind;
	copy.exp = dec.exp;
	copy.form = dec.form;
	copy.mant = dec.mant;
	return copy;
}

/*
 * <sgml> Check one or two numbers for lost digits. </sgml> Arg1 is RHS (or
 * null, if none) Arg2 is current DIGITS setting returns quietly or throws an
 * exception
 */

// --private void checkdigits(com.ibm.icu.math.BigDecimal rhs,int dig){
function checkdigits(rhs, dig) {
	if (dig == 0)
		return; // don't check if digits=0
	// first check lhs...
	if (this.mant.length > dig)
		if ((!(this.allzero(this.mant, dig))))
			throw "Too many digits: " + this.toString();
	if (rhs == null)
		return; // monadic
	if (rhs.mant.length > dig)
		if ((!(this.allzero(rhs.mant, dig))))
			throw "Too many digits: " + rhs.toString();
	return;
}

function round() {
	var len;
	var mode;
	if (round.arguments.length == 2) {
		len = round.arguments[0];
		mode = round.arguments[1];
	} else if (round.arguments.length == 1) {
		var set = round.arguments[0];
		len = set.digits;
		mode = set.roundingMode;
	} else {
		throw "round(): " + round.arguments.length
				+ " arguments given; expected 1 or 2";
	}
	// int adjust;
	var adjust;
	// int sign;
	var sign;
	// byte oldmant[];
	var oldmant;
	// boolean reuse=false;
	var reuse = false;
	// --byte first=0;
	var first = 0;
	// --int increment;
	var increment;
	// --byte newmant[]=null;
	var newmant = null;
	adjust = this.mant.length - len;
	if (adjust <= 0)
		return this; // nowt to do

	this.exp = this.exp + adjust; // exponent of result
	sign = this.ind; // save [assumes -1, 0, 1]
	oldmant = this.mant; // save
	if (len > 0) {
		// remove the unwanted digits
		this.mant = new Array(len);
		// --java.lang.System.arraycopy((java.lang.Object)oldmant,0,(java.lang.Object)mant,0,len);
		this.arraycopy(oldmant, 0, this.mant, 0, len);
		reuse = true; // can reuse mantissa
		first = oldmant[len]; // first of discarded digits
	} else {/* len<=0 */
		this.mant = this.ZERO.mant;
		this.ind = this.iszero;
		reuse = false; // cannot reuse mantissa
		if (len == 0)
			first = oldmant[0];
		else
			first = 0; // [virtual digit]
	}

	// decide rounding adjustment depending on mode, sign, and discarded digits
	increment = 0; // bumper
	{
		modes: do {/* select */
			if (mode == this.ROUND_HALF_UP) { // default first [most common]
				if (first >= 5)
					increment = sign;
			} else if (mode == this.ROUND_UNNECESSARY) { // default for
				// setScale()
				// discarding any non-zero digits is an error
				if ((!(this.allzero(oldmant, len))))
					throw "round(): Rounding necessary";
			} else if (mode == this.ROUND_HALF_DOWN) { // 0.5000 goes down
				if (first > 5)
					increment = sign;
				else if (first == 5)
					if ((!(this.allzero(oldmant, len + 1))))
						increment = sign;
			} else if (mode == this.ROUND_HALF_EVEN) { // 0.5000 goes down if
				// left digit even
				if (first > 5)
					increment = sign;
				else if (first == 5) {
					if ((!(this.allzero(oldmant, len + 1))))
						increment = sign;
					else /* 0.5000 */
					if ((((this.mant[this.mant.length - 1]) % 2)) == 1)
						increment = sign;
				}
			} else if (mode == this.ROUND_DOWN)
				; // never increment
			else if (mode == this.ROUND_UP) { // increment if discarded
				// non-zero
				if ((!(this.allzero(oldmant, len))))
					increment = sign;
			} else if (mode == this.ROUND_CEILING) { // more positive
				if (sign > 0)
					if ((!(this.allzero(oldmant, len))))
						increment = sign;
			} else if (mode == this.ROUND_FLOOR) { // more negative
				if (sign < 0)
					if ((!(this.allzero(oldmant, len))))
						increment = sign;
			} else {
				throw "round(): Bad round value: " + mode;
			}
		} while (false);
	}/* modes */

	if (increment != 0) {
		bump: do {
			if (this.ind == this.iszero) {
				// we must not subtract from 0, but result is trivial anyway
				this.mant = this.ONE.mant;
				this.ind = increment;
			} else {
				// mantissa is non-0; we can safely add or subtract 1
				if (this.ind == this.isneg)
					increment = -increment;
				newmant = this.byteaddsub(this.mant, this.mant.length,
						this.ONE.mant, 1, increment, reuse);
				if (newmant.length > this.mant.length) { // had a carry
					// drop rightmost digit and raise exponent
					this.exp++;
					// mant is already the correct length
					// java.lang.System.arraycopy((java.lang.Object)newmant,0,(java.lang.Object)mant,0,mant.length);
					this.arraycopy(newmant, 0, this.mant, 0, this.mant.length);
				} else
					this.mant = newmant;
			}
		} while (false);
	}/* bump */
	// rounding can increase exponent significantly
	if (this.exp > this.MaxExp)
		throw "round(): Exponent Overflow: " + this.exp;
	return this;
}

function allzero(array, start) {
	// --int i=0;
	var i = 0;
	if (start < 0)
		start = 0;
	{
		var $25 = array.length - 1;
		i = start;
		i: for (; i <= $25; i++) {
			if (array[i] != 0)
				return false;
		}
	}/* i */
	return true;
}

function finish(set, strip) {
	// --int d=0;
	var d = 0;
	// --int i=0;
	var i = 0;
	// --byte newmant[]=null;
	var newmant = null;
	// --int mag=0;
	var mag = 0;
	// --int sig=0;
	var sig = 0;
	/* Round if mantissa too long and digits requested */
	if (set.digits != 0)
		if (this.mant.length > set.digits)
			this.round(set);

	/*
	 * If strip requested (and standard formatting), remove insignificant
	 * trailing zeros.
	 */
	if (strip)
		if (set.form != MathContext.prototype.PLAIN) {
			d = this.mant.length;
			/* see if we need to drop any trailing zeros */
			{
				i = d - 1;
				i: for (; i >= 1; i--) {
					if (this.mant[i] != 0)
						break i;
					d--;
					this.exp++;
				}
			}/* i */
			if (d < this.mant.length) {/* need to reduce */
				newmant = new Array(d);
				// --java.lang.System.arraycopy((java.lang.Object)this.mant,0,(java.lang.Object)newmant,0,d);
				this.arraycopy(this.mant, 0, newmant, 0, d);
				this.mant = newmant;
			}
		}

	this.form = MathContext.prototype.PLAIN; // preset

	/* Now check for leading- and all- zeros in mantissa */
	{
		var $26 = this.mant.length;
		i = 0;
		i: for (; $26 > 0; $26--, i++) {
			if (this.mant[i] != 0) {
				// non-0 result; ind will be correct
				// remove leading zeros [e.g., after subtract]
				if (i > 0) {
					delead: do {
						newmant = new Array(this.mant.length - i);
						// --java.lang.System.arraycopy((java.lang.Object)this.mant,i,(java.lang.Object)newmant,0,this.mant.length-i);
						this.arraycopy(this.mant, i, newmant, 0,
								this.mant.length - i);
						this.mant = newmant;
					} while (false);
				}/* delead */
				// now determine form if not PLAIN
				mag = this.exp + this.mant.length;
				if (mag > 0) { // most common path
					if (mag > set.digits)
						if (set.digits != 0)
							this.form = set.form;
					if ((mag - 1) <= this.MaxExp)
						return this; // no overflow; quick return
				} else if (mag < (-5))
					this.form = set.form;
				/* check for overflow */
				mag--;
				if ((mag < this.MinExp) || (mag > this.MaxExp)) {
					overflow: do {
						// possible reprieve if form is engineering
						if (this.form == MathContext.prototype.ENGINEERING) {
							sig = mag % 3; // leftover
							if (sig < 0)
								sig = 3 + sig; // negative exponent
							mag = mag - sig; // exponent to use
							// 1999.06.29: second test here must be MaxExp
							if (mag >= this.MinExp)
								if (mag <= this.MaxExp)
									break overflow;
						}
						throw "finish(): Exponent Overflow: " + mag;
					} while (false);
				}/* overflow */
				return this;
			}
		}
	}/* i */

	// Drop through to here only if mantissa is all zeros
	this.ind = this.iszero;
	{/* select */
		if (set.form != MathContext.prototype.PLAIN)
			this.exp = 0; // standard result; go to '0'
		else if (this.exp > 0)
			this.exp = 0; // +ve exponent also goes to '0'
		else {
			// a plain number with -ve exponent; preserve and check exponent
			if (this.exp < this.MinExp)
				throw "finish(): Exponent Overflow: " + this.exp;
		}
	}
	this.mant = this.ZERO.mant; // canonical mantissa
	return this;
}
